/**
 * 地图工具类
 * 与业务无关的地图操作方法
 * 主要用于arcgis的api或者对象的生成之类的
 */
import { loadModules as loadESRIModules } from "esri-loader";
import mapConstants from "./mapConstants.js";

/** 生成一个随机唯一码 */
const createUUID = () => {
    return "xxxxxxxx".replace(/[xy]/g, function (c) {
        var r = (Math.random() * 16) | 0,
            v = c == "x" ? r : (r & 0x3) | 0x8;
        return v.toString(16);
    });
};

/** 创建地图标记图标 */
const buildMarker = async ({ center, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.EVENT,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const point = await buildPoint(center);
    const pictureGraphic = new Graphic({
        geometry: point,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "marker",
            },
            attributes
        ),
    });
    return pictureGraphic;
};

/**
 * 生成Point对象
 * 默认4326坐标系
 * @param {*} latlng
 * @returns
 */
const buildPoint = async latlng => {
    const [Point] = await loadESRIModules(["esri/geometry/Point"]);
    const point = new Point({
        x: latlng[1],
        y: latlng[0],
        spatialReference: {
            wkid: 4326,
        },
    });
    return point;
};

const buildPointWithWkid = async (latlng, wkid) => {
    var webMercator;
    if (!isNaN(wkid)) {
        // 如果wkid是指定数字，则为当前地图坐标系转换为指定的坐标系
        webMercator = new SpatialReference({
            wkid: wkid,
        });
    } else {
        // 否则就是直接传入对象
        webMercator = wkid;
    }
    const [Point] = await loadESRIModules(["esri/geometry/Point"]);
    const point = new Point({
        x: latlng[1],
        y: latlng[0],
        spatialReference: webMercator,
    });
    return point;
};

/** 生成事件标记点 */
const buildEventPoint = async ({ center, label, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.EVENT,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const point = await buildPoint(center);
    const pictureGraphic = new Graphic({
        geometry: point,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "event",
            },
            attributes
        ),
    });
    let textSymbol = {
        type: "text", // autocasts as new PictureMarkerSymbol()
        text: label,
        color: "#FFFFFF",
        font: {
            size: "14px",
        },
        xoffset: 0,
        yoffset: 35,
    };
    const textGraphic = new Graphic({
        geometry: point,
        symbol: textSymbol,
        attributes: Object.assign(
            {
                tag: "event",
            },
            attributes
        ),
    });
    return [pictureGraphic, textGraphic];
};

/** 生成事件标记点 */
const buildCameraPoint = async ({ center, label, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.CAMERA,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const pictureGraphic = new Graphic({
        geometry: center,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "camera",
            },
            attributes
        ),
    });
    let textSymbol = {
        type: "text", // autocasts as new PictureMarkerSymbol()
        text: label,
        color: "#FFFFFF",
        font: {
            size: "14px",
        },
        xoffset: 0,
        yoffset: 35,
    };
    const textGraphic = new Graphic({
        geometry: center,
        symbol: textSymbol,
        attributes: Object.assign(
            {
                tag: "camera",
            },
            attributes
        ),
    });
    return [pictureGraphic, textGraphic];
};

/** 生成事件标记点 */
const buildUserPoint = async ({ center, label, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.PERSON,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const pictureGraphic = new Graphic({
        geometry: center,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "user-icon",
            },
            attributes
        ),
    });
    let textSymbol = {
        type: "text", // autocasts as new PictureMarkerSymbol()
        text: label,
        color: "#FFFFFF",
        font: {
            size: "14px",
        },
        xoffset: 0,
        yoffset: 35,
    };
    const textGraphic = new Graphic({
        geometry: center,
        symbol: textSymbol,
        attributes: Object.assign(
            {
                tag: "user-label",
            },
            attributes
        ),
    });
    return [pictureGraphic, textGraphic];
};

/** 生成事件标记点 */
const buildCarPoint = async ({ center, label, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.CAR,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const pictureGraphic = new Graphic({
        geometry: center,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "car-icon",
            },
            attributes
        ),
    });
    let textSymbol = {
        type: "text", // autocasts as new PictureMarkerSymbol()
        text: label,
        color: "#FFFFFF",
        font: {
            size: "14px",
        },
        xoffset: 0,
        yoffset: 35,
    };
    const textGraphic = new Graphic({
        geometry: center,
        symbol: textSymbol,
        attributes: Object.assign(
            {
                tag: "car-label",
            },
            attributes
        ),
    });
    return [pictureGraphic, textGraphic];
};

/** 生成事件标记点 */
const buildResourcePoint = async ({ center, label, attributes }) => {
    let mapResUrl = await mapConstants.mapResUrl();
    let symbol = {
        type: "picture-marker", // autocasts as new PictureMarkerSymbol()
        url: mapResUrl + mapConstants.MAP_MARKER_ICON.RESOURCE,
        width: "32px",
        height: "40px",
        yoffset: 15,
    };
    const [Graphic] = await loadESRIModules(["esri/Graphic"]);
    const pictureGraphic = new Graphic({
        geometry: center,
        symbol: symbol,
        attributes: Object.assign(
            {
                tag: "resource-icon",
            },
            attributes
        ),
    });
    let textSymbol = {
        type: "text", // autocasts as new PictureMarkerSymbol()
        text: label,
        color: "#FFFFFF",
        font: {
            size: "14px",
        },
        xoffset: 0,
        yoffset: 35,
    };
    const textGraphic = new Graphic({
        geometry: center,
        symbol: textSymbol,
        attributes: Object.assign(
            {
                tag: "resource-label",
            },
            attributes
        ),
    });
    return [pictureGraphic, textGraphic];
};

/**
 * 转换地图坐标
 *
 * @param {*} coordinate 转换的坐标 Point类型
 * @param {*} wkid 目标坐标系
 * @returns
 */
const transformCoordinate = async (coordinate, wkid) => {
    let [projection, SpatialReference] = await loadESRIModules(["esri/geometry/projection", "esri/geometry/SpatialReference"]);
    var webMercator;
    if (!isNaN(wkid)) {
        // 如果wkid是指定数字，则为当前地图坐标系转换为指定的坐标系
        webMercator = new SpatialReference({
            wkid: wkid,
        });
    } else {
        // 否则就是直接传入对象
        webMercator = wkid;
    }
    await projection.load();
    return projection.project(coordinate, webMercator);
};

/** 加载地图api组件 */
const loadModules = async modules => {
    let options = await mapConstants.mapOptions();
    return await loadESRIModules(modules, options);
};

const getMapServerUrl = async () => {
    return await mapConstants.mapServerUrl();
};

export default {
    createUUID,
    buildMarker,
    buildPoint,
    buildPointWithWkid,
    buildEventPoint,
    buildCameraPoint,
    buildCarPoint,
    transformCoordinate,
    loadModules,
    getMapServerUrl,
    buildUserPoint,
    buildResourcePoint,
};
